#include "ClientCommands.h"
#include "HexABin.h"

void ClientCommand::parametros(std::string p){ params = p;}

void NewFileCommand::execute(FileSyncHandler& fSyncHandler, Comunicador& comu) {
	std::string mensajeAEnviar = GETFILE, mensajeRecibido, aux;
	mensajeAEnviar += " ";
	mensajeAEnviar += this->params.c_str();

	// mensajeAEnviar = GETFILE nombreArchivo
	comu.enviarMensaje(mensajeAEnviar);
	comu.recibirMensaje(mensajeRecibido);

	// Me devuelve la data
	fSyncHandler.crearArchivo(this->params.c_str(), mensajeRecibido.c_str());
}

void UpdateFileCommand::execute(FileSyncHandler& fSyncHandler, Comunicador& comu){
	// Parametros: nombreArchivo, fechaModificacion
	std::string mensajeAServer = UPDATEFILE, mensajeRecibido, fileFullPath,
			filename, testUpdate = TRYUPDATEUP, oldHash, aux, mensajeDelta;
	std::stringstream stream(this->params);
	// obtengo nombre de archivo
	stream >> filename;
	mensajeAServer += " ";
	mensajeAServer += filename;
	aux.clear();
	// obtengo fileDate
	stream >> aux;
	mensajeAServer += " ";
	mensajeAServer += aux;
	//obtengo hash viejo
	stream >> oldHash;

	// Consigo el path completo del archivo
	fileFullPath = fSyncHandler.getSyncPath();
	fileFullPath += filename;

	/* Seteo el mensaje al delta como emisor (por default, le quiero enviar una
	 * modificacion al server, a menos que este me lo impida en el TRYUPDATE
	 * mensajeDelta = EMISOR + FECHAMODIFICACION
	 */
	mensajeDelta = EMISORDELTA;
	mensajeDelta += " ";
	mensajeDelta += aux;

	// Primero me aseguro que el UPDATE es bueno (TRYUPDATEUP)
	testUpdate += " ";
	testUpdate += filename;
	testUpdate += " ";
	testUpdate += oldHash;

	// Verifico el UPDATE con el server
	comu.enviarMensaje(testUpdate);
	comu.recibirMensaje(mensajeRecibido);

	if (mensajeRecibido.compare(LOGINFAIL) == 0) {
		// Conflicto. Copio archivo actual como backup en mi repo
		fSyncHandler.backUpFile(filename);
		// Si es fail, me vuelvo receptor del delta
		mensajeDelta.clear();
		mensajeDelta = RECEPTORDELTA;
	}

	// Actualizo las modificaciones con delta encoding
	DeltaHandler dHandler(comu);
	dHandler.manejarDelta(mensajeDelta, fileFullPath);
	if (!(dHandler.esEmisor())) {
		// Actualiza el indice con el nuevo hash!
		fSyncHandler.actualizarIndice(filename);
	}
}

void ErasedFileCommand::execute(FileSyncHandler& fSyncHandler, Comunicador& comu) {
	fSyncHandler.borrarArchivo(this->params.c_str());
}


// Notificacion de modificacion, SIEMPRE soy RECEPTOR en el DELTA
void UpdatedFileCommand::execute(FileSyncHandler& fSyncHandler, Comunicador& comu) {
	std::string hashActual, testUpdate = TRYUPDATEDOWN, mensajeRecibido,
			mensajeAServer = UPDATEFILE,
			fileFullPath(fSyncHandler.getSyncPath() + this->params);

	/* En params esta el nombre del archivo. Obtiene el hash actual local para
	 * verificar si se modifico en el transcurso de polling anterior y notificacion
	 */
	hashActual = fSyncHandler.getHashArchivo(this->params);
	testUpdate += " ";
	testUpdate += this->params;
	testUpdate += " ";
	testUpdate += hashActual;
	comu.enviarMensaje(testUpdate);
	comu.recibirMensaje(mensajeRecibido);

	// SI el archivo fue modificado deberia hacer un back up para el user
	if (mensajeRecibido.compare(LOGINFAIL) == 0) {
		fSyncHandler.backUpFile(this->params);
	}
	mensajeRecibido.clear();

	// Siempre soy receptor en este caso de notificacion
	mensajeRecibido = RECEPTORDELTA;

	DeltaHandler dHandler(comu);
	dHandler.manejarDelta(mensajeRecibido, fileFullPath, true);
	// Actualiza el indice con el nuevo hash!
	fSyncHandler.actualizarIndice(this->params);
}

void UploadFileCommand::execute(FileSyncHandler& fSyncHandler, Comunicador& comu) {
	std::string mensajeAEnviar(UPLOADFILE), mensajeRecibido;
	mensajeAEnviar += " ";
	mensajeAEnviar += this->params;
	// mensajeAEnviar: UPLOADFILE nombreArchivo data
	comu.enviarMensaje(mensajeAEnviar);
	comu.recibirMensaje(mensajeRecibido);
}

void EraseFileCommand::execute(FileSyncHandler& fSyncHandler, Comunicador& comu) {
	std::string mensajeAEnviar(ERASEFILE), mensajeRecibido;
	mensajeAEnviar += " ";
	mensajeAEnviar += this->params;
	// mensajeAEnviar : ERASEFILE nombreArchivo
	comu.enviarMensaje(mensajeAEnviar);
	comu.recibirMensaje(mensajeRecibido);
}
